home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / recio202.zip / recio.c < prev    next >
C/C++ Source or Header  |  1994-05-05  |  14KB  |  406 lines

  1. /*****************************************************************************
  2.    MODULE: recio.c
  3.   PURPOSE: record input/output functions
  4. COPYRIGHT: (C) 1994 William Pierpoint
  5.  COMPILER: Borland C Version 3.1
  6.        OS: MSDOS Version 6.2
  7.   VERSION: 2.02
  8.   RELEASE: May 5, 1994
  9. *****************************************************************************/
  10.  
  11. #include <ctype.h>
  12. #include <errno.h>
  13. #include <float.h>
  14. #include <limits.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18.  
  19. #include "recio.h"
  20.  
  21. #define rcol(rp)         ((rp)->r_colno)
  22. #define rflags(rp)       ((rp)->r_flags)
  23. #define rfd(rp)          ((rp)->r_fd)
  24. #define rfp(rp)          ((rp)->r_fp)
  25. #define rreclen(rp)      ((rp)->r_reclen)
  26. #define rrecsiz(rp)      ((rp)->r_recsiz)
  27. #define rfldsiz(rp)      ((rp)->r_fldsiz)
  28. #define rfldch(rp)       ((rp)->r_fldch)
  29. #define rtxtch(rp)       ((rp)->r_txtch)
  30.  
  31. /* private module variables */
  32. static REC *_RECS = NULL;              /* ptr to array of REC structures */
  33.  
  34. static REC rin  = { 1,      0,    stdin,  "stdin",     0L,
  35.                     0,      0,        0,        0,   NULL, 
  36.                     0,   NULL, RECFLDCH, RECTXTCH,  RECIN };
  37.  
  38. static REC rout = { 2, _R_WRT,   stdout, "stdout",     0L, 
  39.                     0,      0,        0,        0,   NULL, 
  40.                     0,   NULL, RECFLDCH, RECTXTCH, RECOUT };
  41.  
  42. static REC rerr = { 3, _R_WRT,   stderr, "stderr",     0L, 
  43.                     0,      0,        0,        0,   NULL, 
  44.                     0,   NULL, RECFLDCH, RECTXTCH, RECERR };
  45.  
  46. #if defined (__MSDOS__) || (MSDOS)
  47. static REC rprn = { 4, _R_WRT,   stdprn, "stdprn",     0L, 
  48.                     0,      0,        0,        0,   NULL, 
  49.                     0,   NULL, RECFLDCH, RECTXTCH, RECPRN };
  50. #define NREC      4          /* number of static record streams */
  51. #else
  52. #define NREC      3
  53. #endif
  54. #define ROPEN_MIN NREC       /* reserved for recin, etc */
  55. #define ROPEN     max(ROPEN_MAX, ROPEN_MIN)
  56.  
  57. /* public variables */
  58. REC *recin = &rin;
  59. REC *recout = &rout;
  60. REC *recerr = &rerr;
  61. #if defined (__MSDOS__) || (MSDOS)
  62. REC *recprn = &rprn;
  63. #endif
  64.  
  65. /* friend variables */
  66. char _r_nsbuf[NSBUFSIZ];     /* buffer for numeric to string conversions */
  67.  
  68. /* Support functions */
  69. /****************************************************************************/
  70. static void                  /* returns nothing                             */
  71.     _rexit(                  /* at program exit, clean up                   */
  72.         void)                /* no arguments                                */
  73. /****************************************************************************/
  74. {
  75.     /* free recin buffers */
  76.     free(rflds(recin));
  77.     free(rrecs(recin));
  78.     rflds(recin) = NULL;
  79.     rfldsiz(recin) = 0;
  80.     rrecs(recin) = NULL;
  81.     rrecsiz(recin) = 0;
  82.     rreclen(recin) = 0;
  83.  
  84.     /* ensure all record streams closed */
  85.     rcloseall();
  86. }
  87.  
  88. /****************************************************************************/
  89. void                         /* return error number (0=no error)            */
  90.     _rsetexitfn(             /* register _rexit function with atexit()      */
  91.         REC *rp)             /* record pointer                              */
  92. /****************************************************************************/
  93. {
  94.     static int once=0;       /* register exit fn only once */
  95.  
  96.     if (!once) {
  97.  
  98.         /* execute this path at most one time */
  99.         once++;
  100.  
  101.         /* if atexit() fails to register _rexit() function */
  102.         if (atexit(_rexit)) {
  103.  
  104.            /* register warning */
  105.            rsetwarn(rp, R_WNOREG);
  106.         }
  107.     }
  108.  
  109. /****************************************************************************/
  110. int                          /* return error number (0=no error)            */
  111.     _rismode(                /* check for correct mode                      */
  112.         REC *rp,             /* record pointer                              */
  113.         int mode)            /* mode (0=read; !0=write/append)              */
  114. /****************************************************************************/
  115. {
  116.     int errnum=0;            /* error number (0=mode ok, !0=invalid mode) */
  117.     unsigned smode;          /* stream mode */
  118.  
  119.     /* if stream _R_WRT flag does not match mode */
  120.     smode = rflags(rp) & _R_WRT;
  121.     if ((mode && !smode) || (!mode && smode)) {
  122.         errnum = rseterr(rp, R_EINVMOD);
  123.     }
  124.     return errnum;
  125. }
  126.  
  127. /****************************************************************************/
  128. int                          /* return error number (0=no error)            */
  129.     _rstatus(                /* check stream for errors                     */
  130.         REC *rp,             /* record pointer                              */
  131.         int mode)            /* mode (0=read; !0=write/append)              */
  132. /****************************************************************************/
  133. {
  134.     int errnum=0;            /* error number */
  135.  
  136.     /* test for valid record pointer */
  137.     if (!risvalid(rp)) {
  138.         errnum = rseterr(NULL, EINVAL);
  139.         goto done;
  140.     }
  141.     
  142.     /* check mode */
  143.     errnum = _rismode(rp, mode);
  144.     if (errnum) goto done;
  145.  
  146.     /* if record 0 and write mode */
  147.     if (!rrecno(rp) && mode) {
  148.         rrecno(rp)++;
  149.     }
  150.  
  151.     /* test for previous error */
  152.     errnum = rerror(rp);
  153.  
  154. done:
  155.     return (errnum);
  156. }
  157.  
  158. /****************************************************************************/
  159. static void                  /* returns nothing                             */
  160.     _rfree(                  /* free the memory allocated to a record       */
  161.         REC *rp)             /* record pointer                              */
  162. /****************************************************************************/
  163. {
  164.     if (risvalid(rp)) {
  165.         free(rflds(rp));
  166.         free(rrecs(rp));
  167.         if (rfp(rp)) fclose(rfp(rp));
  168.         memset(rp, 0, sizeof(REC));
  169.     }
  170. }
  171.  
  172. /* User functions */
  173. /****************************************************************************/
  174. REC *                        /* return record pointer                       */
  175.     ropen(                   /* open a record stream for reading            */
  176.         const char *fname,   /* name of file to open                        */
  177.         const char *mode)    /* type of mode used to open file              */
  178. /****************************************************************************/
  179. {
  180.     REC *rp = _RECS;         /* record pointer */
  181.     int  i;                  /* count of REC structures */
  182.     int  ch;                 /* first character of mode */
  183.     
  184.     errno = 0;
  185.  
  186.     /* only modes currently supported are "r", "w", and "a" */
  187.     ch = tolower(*mode);
  188.     if (!(ch=='r' || ch=='w' || ch=='a')) {
  189.         rp = NULL;
  190.         rseterr(NULL, EINVAL);
  191.         goto done;
  192.     }
  193.  
  194.     /* allocate memory for array of REC structures */
  195.     if (!rp) {
  196.         do {
  197.             /* note: no memory allocation needed for recin, etc */
  198.             rp = _RECS = (REC *) calloc(ROPEN-NREC, sizeof(REC));
  199.             if (!rp) {
  200.                 if (rseterr(NULL, ENOMEM)) goto done;
  201.             }
  202.         } while (!rp);
  203.     }
  204.  
  205.     /* search thru REC structures until empty position found */
  206.     for (i=NREC+1; i <= ROPEN; i++, rp++) {
  207.         if (!rfd(rp)) {
  208.             rfd(rp) = i;
  209.             break;
  210.         }
  211.     }
  212.     /* error if out of positions */
  213.     if (i > ROPEN) {
  214.         rp = NULL;
  215.         rseterr(NULL, EMFILE);
  216.         goto done;
  217.     }
  218.  
  219.     /* open file */
  220.     rfp(rp) = fopen(fname, mode);
  221.     if (!rfp(rp)) {
  222.         rclose(rp);
  223.         rp = NULL;
  224.         /* if error other than path/file not found */
  225.         if (errno != ENOENT) {
  226.             rseterr(NULL, errno);
  227.         }
  228.         goto done;
  229.     }
  230.  
  231.     /* initialize */
  232.     if (ch != 'r') rflags(rp)  |= _R_WRT;
  233.     rnames(rp)  = fname;
  234.     rrecno(rp)  = 0L;
  235.     rfldno(rp)  = 0;
  236.     rcol(rp)    = 0;
  237.     rrecsiz(rp) = 0;
  238.     rreclen(rp) = 0;
  239.     rrecs(rp)   = NULL;
  240.     rfldsiz(